/*
 * @Description: 离线装饰器工具
 * @Author: duan_shuangjun 丶
 * @Date: 2025-09-17 10:55:00
 */

import { isOnline } from './network'
import { ElMessage } from 'element-plus'


/**
 * 调用离线模式
 */
async function callOfflineMode(
    domain: string,
    action: string,
    args: any[],
    offlineParams?: (args: any[]) => any
) {
    try {
        const payload = offlineParams ? offlineParams(args) : (args[0] || {})
        const result = await window.api.invoke(domain, action, payload)
        console.log('离线模式结果:', result)
        // 统一处理离线响应状态
        if (result?.status !== 200) {
            const message = result?.message || '离线操作失败'
            ElMessage.error(`离线模式:${message}`)
            console.error('离线模式错误:', result)

            // 返回错误响应，让业务代码知道操作失败
            return {
                status: result?.status || 500,
                message,
                data: result?.data || null
            }
        }

        return result
    } catch (error: any) {
        const message = error?.message || '离线模式调用失败'
        ElMessage.error(`离线模式异常:${message}`)
        console.error('离线模式异常:', error)

        return {
            status: 500,
            message,
            data: null
        }
    }
}

/**
 * 判断是否为网络错误
 */
function isNetworkError(error: any): boolean {
    const networkErrorCodes = [
        'ERR_NETWORK',
        'ERR_INTERNET_DISCONNECTED',
        'NETWORK_ERROR',
        'TIMEOUT'
    ]

    return networkErrorCodes.some(code =>
        error?.code === code ||
        error?.message?.includes(code) ||
        error?.message?.includes('Network Error')
    )
}

/**
 * 懒加载装饰器 - 只有在实际调用时才执行逻辑
 */
export function offlineApi(domain: string, action: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value

        // 返回一个包装函数，只有在实际调用时才执行
        descriptor.value = function (...args: any[]) {
            return (async () => {
                const online = await isOnline()

                if (online) {
                    // 在线模式：执行原始方法
                    try {
                        return await originalMethod.apply(this, args)
                    } catch (error: any) {
                        // 在线失败时，如果错误是网络相关，尝试离线模式
                        if (isNetworkError(error)) {
                            console.warn(`在线请求失败，切换到离线模式: ${action}`, error)
                            return await callOfflineMode(domain, action, args)
                        }
                        throw error
                    }
                } else {
                    // 离线模式：直接调用 IPC
                    return await callOfflineMode(domain, action, args)
                }
            })()
        }

        return descriptor
    }
}

/**
 * 自定义离线参数处理装饰器 - 懒加载版本
 */
export function offlineApiWithParams(
    domain: string,
    action: string,
    paramMapper: (args: any[]) => any
) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value

        // 返回一个包装函数，只有在实际调用时才执行
        descriptor.value = function (...args: any[]) {
            return (async () => {
                const online = await isOnline()

                if (online) {
                    // 在线模式：执行原始方法
                    try {
                        return await originalMethod.apply(this, args)
                    } catch (error: any) {
                        // 在线失败时，如果错误是网络相关，尝试离线模式
                        if (isNetworkError(error)) {
                            console.warn(`在线请求失败，切换到离线模式: ${action}`, error)
                            return await callOfflineMode(domain, action, args, paramMapper)
                        }
                        throw error
                    }
                } else {
                    // 离线模式：直接调用 IPC
                    return await callOfflineMode(domain, action, args, paramMapper)
                }
            })()
        }

        return descriptor
    }
}
